﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Configuration;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace bwc
{
    public partial class Form1 : Form
    {
        public delegate int EnumThreadWindowsCallback(IntPtr wnd,IntPtr edata);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool EnumChildWindows(IntPtr parent,EnumThreadWindowsCallback callback, IntPtr extraData);
        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern void ShowWindow(IntPtr wnd,int how);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle rect);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern bool SetWindowPos(IntPtr hWnd,IntPtr hWndInsertAfter,int X,int Y,int cx,int cy,uint uFlags);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern int GetClassNameW(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr UpdateWindow(IntPtr hWnd);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr InvalidateRect(IntPtr hWnd,ref Rectangle rect,bool bErase);

        bool fullclose = false;
        bool first = true;
        private DataTable wnds = new DataTable("windows");
        private DataTable menu = new DataTable("menu");
        private Configuration conf = null;
        private string[] xwnds=null;
        private String[] xcmd = null;
        public Form1()
        {
            InitializeComponent();
            wnds.Columns.Add("name", typeof(String));
            wnds.Columns.Add("caption", typeof(String));
            wnds.Columns.Add("class", typeof(String));
            menu.Columns.Add("name",typeof(String));
            menu.Columns.Add("action", typeof(String));
            menu.Columns.Add("windows", typeof(String));
            dataGridView1.DataSource = wnds;
            dataGridView2.DataSource = menu;
            conf = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            LoadOptions();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            notifyIcon1.Icon = Icon;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = !fullclose;
            WindowState = FormWindowState.Minimized;
            Hide();
        }

        private void закрытьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fullclose = true;
            Close();
        }

        private void настройкиToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            LoadOptions();
            Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SaveOptions();
            Close();
        }

        private void Form1_Activated(object sender, EventArgs e)
        {
            if (first)
            {
                Close();
                first = false;
            }
        }

        private void updateMenu()
        {
            while(contextMenuStrip1.Items.Count>3)
                contextMenuStrip1.Items.RemoveAt(3);
            for (int i = 0; i < menu.Rows.Count; i++)
            {
                ToolStripItem it=contextMenuStrip1.Items.Add(menu.Rows[i][0] as string);
                it.Tag=i.ToString();
                it.Click+=new EventHandler(this.onMenu);
            }
        }

        private void LoadOptions()
        {
            KeyValueConfigurationCollection c=conf.AppSettings.Settings;
            if (c["wndc"] == null)
                return;
            int cn = int.Parse(c["wndc"].Value);
            wnds.Rows.Clear();
            for (int i = 0; i < cn; i++)
                wnds.Rows.Add(c["wname" + i.ToString()].Value, c["wcap" + i.ToString()].Value, c["wcls" + i.ToString()].Value);
            cn = int.Parse(c["menc"].Value);
            for (int i = 0; i < cn; i++)
                menu.Rows.Add(c["mname" + i.ToString()].Value, c["mact" + i.ToString()].Value, c["mwnds" + i.ToString()].Value);
            updateMenu();
        }

        private void SaveOptions()
        {
            conf.AppSettings.Settings.Clear();
            conf.AppSettings.Settings.Add("wndc",wnds.Rows.Count.ToString());
            conf.AppSettings.Settings.Add("menc", menu.Rows.Count.ToString());
            for (int i = 0; i < wnds.Rows.Count; i++)
            {
                conf.AppSettings.Settings.Add("wname"+i.ToString(),wnds.Rows[i][0] as string);
                conf.AppSettings.Settings.Add("wcap" + i.ToString(), wnds.Rows[i][1] as string);
                conf.AppSettings.Settings.Add("wcls" + i.ToString(), wnds.Rows[i][2] as string);
            }
            for (int i = 0; i < menu.Rows.Count; i++)
            {
                conf.AppSettings.Settings.Add("mname" + i.ToString(), menu.Rows[i][0] as string);
                conf.AppSettings.Settings.Add("mact" + i.ToString(), menu.Rows[i][1] as string);
                conf.AppSettings.Settings.Add("mwnds" + i.ToString(), menu.Rows[i][2] as string);
            }
            conf.Save();
            updateMenu();
        }

        private void onMenu(object sender, EventArgs e)
        {
            int id=int.Parse((sender as ToolStripMenuItem).Tag as String);
            if (menu.Rows.Count<id)
                return;
            xcmd = (menu.Rows[id][1] as String).Split(':');
            xwnds = (menu.Rows[id][2] as String).Split(',');
            EnumChildWindows(GetDesktopWindow(),onfound, new IntPtr());
        }

        public int onfound(IntPtr HWND, IntPtr param)
        {
            StringBuilder s = new StringBuilder(300);
            GetWindowText(HWND, s, 300);
            StringBuilder cs = new StringBuilder(300);
            GetClassNameW(HWND, cs, 300);
            if (haswindow(s.ToString(),cs.ToString()))
            {
                doaction(HWND);
            }
            return 1;
        }

        private int findWndByName(string name)
        {
            for (int i = 0; i < wnds.Rows.Count; i++)
                if ((wnds.Rows[i][0] as string) == name)
                    return i;
            return -1;
        }

        private bool haswindow(String name,String cls)
        {
            for (int i = 0; i < xwnds.Length; i++)
            {
                int id = findWndByName(xwnds[i]);
                if (id < 0) return false;
                string nm = (wnds.Rows[id][1] as string);
                string cl = (wnds.Rows[id][2] as string);
                if (nm!=null && nm!="")
                if (Regex.IsMatch(name,nm))
                    return true;
                if (cl!=null && cl != "") 
                if (Regex.IsMatch(cls, cl))
                    return true;
            }
            return false;
        }

        private void doaction(IntPtr wnd)
        {
            if (xcmd[0] == "flash")
                flashWnd(wnd);
            if (xcmd[0] == "width")
                makeSize(wnd, int.Parse(xcmd[1]), 0);
            if (xcmd[0] == "hieght")
                makeSize(wnd, 0,int.Parse(xcmd[1]));
            if (xcmd[0] == "size")
                makeSize(wnd, int.Parse(xcmd[1]), int.Parse(xcmd[2]));
            if (xcmd[0] == "maximize")
                maximizeWindow(wnd);
        }

        private void flashWnd(IntPtr wnd)
        {
            int SW_SHOW = 5;
            int SW_HIDE = 0;
            ShowWindow(wnd, SW_HIDE);
            System.Threading.Thread.Sleep(100);
            ShowWindow(wnd, SW_SHOW);
            System.Threading.Thread.Sleep(100);
            ShowWindow(wnd, SW_HIDE);
            System.Threading.Thread.Sleep(100);
            ShowWindow(wnd, SW_SHOW);
            System.Threading.Thread.Sleep(100);
        }

        private void makeSize(IntPtr wnd,int w,int h)
        {
            Rectangle rect = new Rectangle();
            ShowWindow(wnd, 9);
            UpdateWindow(wnd);
            GetWindowRect(wnd, ref rect);
            int ww = w;
            int wh = h;
            if (ww == 0)
                ww = rect.Width-rect.X;
            if (wh == 0)
                wh = rect.Height-rect.Y;
            SetWindowPos(wnd, IntPtr.Zero, 0, 0, ww, wh, 2 | 4 | 512);
        }

        private void maximizeWindow(IntPtr wnd)
        {
            ShowWindow(wnd, 9);
            ShowWindow(wnd, 3);
        }

    }
}
